/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { BaseCustomDfuImpl } from './BaseCustomDfuImpl'
import { DfuBaseService } from './DfuBaseService'
import ble from '@ohos.bluetooth.ble';
import hilog from '@ohos.hilog';

export class LegacyDfuImpl extends BaseCustomDfuImpl {
  // UUIDs used by the DFU
  static DEFAULT_DFU_SERVICE_UUID: string = '00001530-1212-EFDE-1523-785FEABCD123';
  static DEFAULT_DFU_CONTROL_POINT_UUID: string = '00001531-1212-EFDE-1523-785FEABCD123';
  static DEFAULT_DFU_PACKET_UUID: string = '00001532-1212-EFDE-1523-785FEABCD123';
  static DEFAULT_DFU_VERSION_UUID: string = '00001534-1212-EFDE-1523-785FEABCD123';

  static DFU_SERVICE_UUID: string = LegacyDfuImpl.DEFAULT_DFU_SERVICE_UUID;
  static DFU_CONTROL_POINT_UUID: string = LegacyDfuImpl.DEFAULT_DFU_CONTROL_POINT_UUID;
  static DFU_PACKET_UUID: string = LegacyDfuImpl.DEFAULT_DFU_PACKET_UUID;
  static DFU_VERSION_UUID: string = LegacyDfuImpl.DEFAULT_DFU_VERSION_UUID;

  private static DFU_STATUS_SUCCESS: number = 1;
  // Operation codes and packets
  private static OP_CODE_START_DFU_KEY: number = 0x01; // 1
  private static OP_CODE_INIT_DFU_PARAMS_KEY: number = 0x02; // 2
  private static OP_CODE_RECEIVE_FIRMWARE_IMAGE_KEY: number = 0x03; // 3
  private static OP_CODE_VALIDATE_KEY: number = 0x04; // 4
  private static OP_CODE_ACTIVATE_AND_RESET_KEY: number = 0x05; // 5
  private static OP_CODE_RESET_KEY: number = 0x06; // 6
  //private static OP_CODE_PACKET_REPORT_RECEIVED_IMAGE_SIZE_KEY = 0x07; // 7
  private static OP_CODE_PACKET_RECEIPT_NOTIF_REQ_KEY: number = 0x08; // 8
  private static OP_CODE_RESPONSE_CODE_KEY: number = 0x10; // 16
  private static OP_CODE_PACKET_RECEIPT_NOTIF_KEY: number = 0x11; // 17
  private static OP_CODE_START_DFU: Uint8Array = new Uint8Array([LegacyDfuImpl.OP_CODE_START_DFU_KEY, 0x00]);
  private static OP_CODE_START_DFU_V1: Uint8Array = new Uint8Array([LegacyDfuImpl.OP_CODE_START_DFU_KEY]);
  private static OP_CODE_INIT_DFU_PARAMS: Uint8Array =
    new Uint8Array([LegacyDfuImpl.OP_CODE_INIT_DFU_PARAMS_KEY]); // SDK 6.0.0 or older
  private static OP_CODE_INIT_DFU_PARAMS_START: Uint8Array =
    new Uint8Array([LegacyDfuImpl.OP_CODE_INIT_DFU_PARAMS_KEY, 0x00]);
  private static OP_CODE_INIT_DFU_PARAMS_COMPLETE: Uint8Array =
    new Uint8Array([LegacyDfuImpl.OP_CODE_INIT_DFU_PARAMS_KEY, 0x01]);
  private static OP_CODE_RECEIVE_FIRMWARE_IMAGE: Uint8Array =
    new Uint8Array([LegacyDfuImpl.OP_CODE_RECEIVE_FIRMWARE_IMAGE_KEY]);
  private static OP_CODE_VALIDATE: Uint8Array = new Uint8Array([LegacyDfuImpl.OP_CODE_VALIDATE_KEY]);
  private static OP_CODE_ACTIVATE_AND_RESET: Uint8Array =
    new Uint8Array([LegacyDfuImpl.OP_CODE_ACTIVATE_AND_RESET_KEY]);
  private static OP_CODE_RESET: Uint8Array = new Uint8Array([LegacyDfuImpl.OP_CODE_RESET_KEY]);
  //private static OP_CODE_REPORT_RECEIVED_IMAGE_SIZE = new byte[] { OP_CODE_PACKET_REPORT_RECEIVED_IMAGE_SIZE_KEY ]);
  private static OP_CODE_PACKET_RECEIPT_NOTIF_REQ: Uint8Array =
    new Uint8Array([LegacyDfuImpl.OP_CODE_PACKET_RECEIPT_NOTIF_REQ_KEY, 0x00, 0x00]);

  private mControlPointCharacteristic: ble.BLECharacteristic;
  private mPacketCharacteristic: ble.BLECharacteristic;

  /**
   * Flag indicating whether the image size has been already transferred or not.
   */
  private mImageSizeInProgress: boolean;

  constructor(service: DfuBaseService) {
    super(service);
    this.TAG = 'LegacyDfuImpl';
    hilog.info(this.DOMAIN, this.TAG, 'LegacyDfuImpl init');
  }

  protected getControlPointCharacteristicUUID(): string {
    return LegacyDfuImpl.DFU_CONTROL_POINT_UUID;
  }

  protected getPacketCharacteristicUUID(): string {
    return LegacyDfuImpl.DFU_PACKET_UUID;
  }

  protected getDfuServiceUUID(): string {
    return LegacyDfuImpl.DFU_SERVICE_UUID;
  }

  public async isClientCompatible(gattServiceList: Array<ble.GattService>): Promise<boolean> {
    hilog.info(this.DOMAIN, this.TAG, 'LegacyDfuImpl isClientCompatible');
    //TODO: find service with spec UUID
    for (const gsItem of gattServiceList) {
      if (gsItem.serviceUuid === LegacyDfuImpl.DFU_SERVICE_UUID) {
        for (const gcItem of gsItem.characteristics) {
          if (gcItem.characteristicUuid === LegacyDfuImpl.DFU_CONTROL_POINT_UUID) {
            for (const gdItem of gcItem.descriptors) {
              if (gdItem.descriptorUuid === LegacyDfuImpl.CLIENT_CHARACTERISTIC_CONFIG.toUpperCase()) {
                this.mControlPointCharacteristic = gcItem;
                hilog.info(this.DOMAIN, this.TAG, 'Is LegacyDfuImpl Client');
                for (const gcItem2 of gsItem.characteristics) {
                  if (gcItem2.characteristicUuid === LegacyDfuImpl.DFU_CONTROL_POINT_UUID) {
                    this.mPacketCharacteristic = gcItem2;
                    return true;
                  }
                }
              }
            }
          }
        }
      }
    }
    return false;
  }

  public shouldScanForBootloader(): boolean {
    return false;
  }

  public finalize(forceRefresh: boolean) {

  };

  public performDfu() {
    hilog.info(this.DOMAIN, this.TAG, 'preformDfu');
  }
}